package org.ala.tiktools.tools;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;

/**
 * 仅仅是KV套一层初始化过程的简单包装
 *
 * @author ala
 * @date 2025-01-09 16:39
 */
public class CachingKVTools<K, V> {

    /**
     *  保存kv
     */
    protected Map<K, Value<V>> map = new ConcurrentHashMap<>();
    /**
     *  空值标签
     */
    protected V NULL;
    /**
     *  通过K拿不到V时的初始化
     */
    protected Function<K, V> init;
    /**
     *  有效期（单位：毫秒）
     */
    protected long validityPeriod;


    public CachingKVTools(V nullTag, Function<K, V> callable) {
        this(nullTag, -1, callable);
    }
    public CachingKVTools(V nullTag, long validityPeriod, Function<K, V> callable) {
        NULL = nullTag;
        init = callable;
        this.validityPeriod = validityPeriod;
    }


    /**
     *  取值
     */
    public V get(K k) {
        Value<V> v = map.get(k);
        if (v == null || (validityPeriod > 0 && System.currentTimeMillis() - v.birth > validityPeriod)) {
            synchronized (k) {
                v = map.get(k);
                if (v == null) {v = new Value<>(init.apply(k));}
                if (v.v == null) {v = new Value<>(NULL);}
                map.put(k, v);
            }
        }
        return v.v == null || NULL.equals(v.v) ? null : v.v;
    }


    /**
     *  值包装器
     */
    protected static class Value<V> {
        V v;
        long birth;
        public Value(V v) {
            this.v = v;
            this.birth = System.currentTimeMillis();
        }
    }
}